package org.example.database_course_design.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.example.database_course_design.entity.DTO.cardIDAndPass;
import org.example.database_course_design.entity.PO.CardTransactionSum;
import org.example.database_course_design.entity.PO.Cardinfo;
import org.example.database_course_design.entity.PO.Tradeinfo;
import org.example.database_course_design.entity.PO.Userinfo;
import org.example.database_course_design.entity.VO.UserForm;
import org.example.database_course_design.mapper.*;
import org.example.database_course_design.service.CustomerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;

@Service
@Transactional
public class CustomerServiceImpl implements CustomerService {
    @Autowired
    private CardinfoMapper cardinfoMapper;

    @Autowired
    private DepositMapper depositMapper;

    @Autowired
    private TradeinfoMapper tradeinfoMapper;

    @Autowired
    private UserinfoMapper userinfoMapper;

    @Autowired
    private CardTransactionSumMapper cardTransactionSumMapper;

    @Override
    public Userinfo update(Userinfo userinfo) {
        int num = userinfoMapper.updateById(userinfo);
        return num == 1? userinfoMapper.selectById(userinfo.getCustomerID()) : null;
    }

    @Override
    public UserForm getBalance(String cardID, String password) {
        Cardinfo c = cardinfoMapper.selectOne(new QueryWrapper<Cardinfo>().eq("cardID", cardID).eq("pass", password));
        if(c == null || c.getIsReportLoss().equals("是")) return null;
        Userinfo u = userinfoMapper.selectById(c.getCustomerID());
        UserForm f = new UserForm();
        f.setCardID(c.getCardID());
        f.setUserName(u.getCustomerName());
        f.setBalance(c.getBalance());
        return f;
    }

    @Override
    public Boolean lost(cardIDAndPass cardIDAndPass) {
        if(cardIDAndPass == null || cardIDAndPass.getCardID().isEmpty() || cardIDAndPass.getPassword().isEmpty())  return false;
        Cardinfo cardinfo = cardinfoMapper.selectOne(
                new QueryWrapper<Cardinfo>()
                        .eq("cardID", cardIDAndPass.getCardID())
                        .eq("pass", cardIDAndPass.getPassword())
        );
        if (cardinfo != null) {
            cardinfo.setIsReportLoss("是");
            int num = cardinfoMapper.updateById(cardinfo);
            return num == 1;
        }
        return false;
    }

    @Override
    public Boolean changeBalance(Cardinfo cardinfo) {
        synchronized (cardinfo.getCardID()) {
            Cardinfo oldCardinfo = cardinfoMapper.selectById(cardinfo.getCardID());
            System.out.println(oldCardinfo.toString());
            if (oldCardinfo != null) {
                if(oldCardinfo.getBalance().add(cardinfo.getBalance()).compareTo(BigDecimal.ZERO) > 0) {
                    oldCardinfo.setBalance(oldCardinfo.getBalance().add(cardinfo.getBalance()));
                    cardinfoMapper.updateById(oldCardinfo);
                    return true;
                } else {
                    return false;
                }
            }
            return false;
        }
    }

    @Override
    public Boolean moveMoney(Cardinfo cardinfo, String cardID) {
        synchronized (cardinfo.getCardID()) {
            Cardinfo oldCardinfo = cardinfoMapper.selectOne(new QueryWrapper<Cardinfo>().eq("cardID", cardinfo.getCardID()));
            Cardinfo getCardinfo = cardinfoMapper.selectOne(new QueryWrapper<Cardinfo>().eq("cardID", cardID));
            if(oldCardinfo != null && getCardinfo != null && oldCardinfo.getBalance().compareTo(cardinfo.getBalance()) >= 0) {
                cardinfoMapper.updateBalance(cardinfo, cardID);
                return true;
            }
        }
        return false;
    }

    @Override
    public Boolean updatePwd(String cardID, String telephone, String newPassword) {
        Cardinfo cardinfo = new Cardinfo();
        cardinfo.setCardID(cardID);
        cardinfo = cardinfoMapper.selectOne(new QueryWrapper<Cardinfo>().eq("cardID", cardID));
        Userinfo u = userinfoMapper.selectById(cardinfo.getCustomerID());
        if(u.getTelephone().equals(telephone)) {
            cardinfo.setPass(newPassword);
            int num = cardinfoMapper.updateById(cardinfo);
            return num == 1;
        }
        return false;
    }

    @Override
    public BigDecimal getBalanceInfo(String cardID) {
        Cardinfo c = cardinfoMapper.selectOne(new QueryWrapper<Cardinfo>().eq("cardID", cardID));
        System.out.println(c.toString());
        if(c == null || c.getIsReportLoss().equals("是")) return null;

        return c.getBalance();
    }

    @Override
    public List<Tradeinfo> getMyTrace(String cardID) {
        return tradeinfoMapper.selectList(new QueryWrapper<Tradeinfo>().eq("cardID", cardID));
    }

    @Override
    public Boolean updatePwdByOld(String cardID, String oldPassword, String newPassword) {
        Cardinfo cardinfo = new Cardinfo();
        cardinfo.setCardID(cardID);
        cardinfo = cardinfoMapper.selectOne(new QueryWrapper<Cardinfo>().eq("cardID", cardID).eq("pass", oldPassword));
        if(cardinfo != null) {
            cardinfo.setPass(newPassword);
            int num = cardinfoMapper.updateById(cardinfo);
            return num == 1;
        }
        return false;
    }

    @Override
    public List<CardTransactionSum> getMyMoneySum(String cardID) {
        return cardTransactionSumMapper.selectList(new QueryWrapper<CardTransactionSum>().eq("cardID", cardID));
    }

    @Override
    public Page<Tradeinfo> getMyTracePage(String cardID, String type, String startDate, String endDate, Integer pageNum, Integer pageSize) {
        QueryWrapper<Tradeinfo> wrapper = new QueryWrapper<>();
        wrapper.eq("cardID", cardID);
        if (type != null && !type.equals("all")) wrapper.eq("tradeType", type);
        if (startDate != null && !startDate.isEmpty()) wrapper.ge("tradeDate", startDate + " 00:00:00");
        if (endDate != null && !endDate.isEmpty()) wrapper.le("tradeDate", endDate + " 23:59:59");
        wrapper.orderByDesc("tradeDate");
        return tradeinfoMapper.selectPage(new Page<>(pageNum, pageSize), wrapper);
    }
}